package com.jboltai.event.text;

import com.jboltai.config.JBoltAIConfig;
import com.jboltai.event.Event;
import com.jboltai.event.EventAttrKey;
import com.jboltai.event.EventType;
import com.jboltai.event.handler.EventHandler;
import com.jboltai.util.text.enums.FormatType;
import com.jboltai.util.text.enums.WebPageMode;

import java.io.File;

/**
 * 文字内容提取事件
 */
public abstract class TextEvent<T extends TextEvent, ResultType, HandlerType extends EventHandler> extends Event<T, ResultType, HandlerType> {

    /**
     * 内部用的attrkey，绑定的对应TextResult
     */
    public static final String INNER_RESULT_KEY = "__inner_result";

    protected TextEvent(EventType type) {
        super(type);
        if (JBoltAIConfig.getMaxTextEventWaitTimeout() > 0) {
            this.waitTimestamp = System.currentTimeMillis() + JBoltAIConfig.getMaxTextEventWaitTimeout();
        } else {
            this.waitTimestamp = 0;
        }
    }

    private IFile2TextConverter file2TextConverter;

    protected File file;


    protected String url;

    /**
     * 是否使用流式获取，可以节省内存
     */
    protected boolean stream;

    /**
     * url无法判断内容类型，是文件还是网页，可以通过该字段指定。默认会自动判断，根据url相应的contentType
     */
    private ContentSourceType contentSourceType = ContentSourceType.AUTO_DETECT;




    private WebPageMode webPageMode;

    /**
     * 获取的html代码如何格式化
     */
    private FormatType formatType;

    /**
     * 从网页提取的话，要提取的元素对应的选择器
     */
    private String contentSelector;

    /**
     * 从网页提取的话，标题对应的选择器，不设置的话，默认会使用head中的title
     */
    private String titleSelector;




    public String getTitleSelector() {
        return titleSelector;
    }

    public T setTitleSelector(String titleSelector) {
        this.titleSelector = titleSelector;
        return (T) this;
    }

    public ContentSourceType getContentSourceType() {
        return contentSourceType;
    }

    public T setContentSourceType(ContentSourceType contentSourceType) {
        this.contentSourceType = contentSourceType;
        return (T) this;
    }

    public WebPageMode getWebPageMode() {
        return webPageMode;
    }

    public T setWebPageMode(WebPageMode webPageMode) {
        this.webPageMode = webPageMode;
        return (T) this;
    }

    public FormatType getHtmlFormatType() {
        return formatType == null ? FormatType.HTML : formatType;
    }

    public T setHtmlFormatType(FormatType formatType) {
        this.formatType = formatType;
        return (T) this;
    }

    public String getContentSelector() {
        return contentSelector == null ? "body" : contentSelector;
    }

    /**
     * 从url抽取html内容时，指定要抽取的元素选择器
     * @param contentSelector
     * @return
     */
    public T setContentSelector(String contentSelector) {
        this.contentSelector = contentSelector;
        return (T) this;
    }


    public File getFile() {
        return file;
    }

    public String getUrl() {
        return url;
    }

    public boolean isStream() {
        return stream;
    }

    /**
     * 设置是否使用流式获取。如果文本内容来自网络请求或者文件，推荐设置成true，可以节省内存。
     * 事件处理器会在处理完每个分块后，执行一次success，<b>所以请注意：流式处理的onSuccess回调会被触发多次，每次只能获取当前被处理的分块，并且
     * 之前的分块不会被存储，在onComplete后，无法通过event.getResult拿到所有分块</b>。
     * @param stream
     * @return
     */
    public T setStream(boolean stream) {
        this.stream = stream;
        return (T) this;
    }

    public T setFile(File file) {

        this.file = file;
        return (T) this;
    }

    public T setUrl(String url) {

        this.url = url;
        return (T) this;
    }


    /**
     * 对于图片和附件的处理, 目前仅支持Word 和 PDF格式。
     * 该回调方法如果返回了一个非空字符串，会尽量以文件出现的位置，作为替代文本拼到到原文中。
     */
    public T onFile(IFile2TextConverter file2TextConverter) {
        this.file2TextConverter = file2TextConverter;
        return (T) this;
    }

    public IFile2TextConverter getFile2TextConverter() {
        return file2TextConverter;
    }

    public void setFile2TextConverter(IFile2TextConverter file2TextConverter) {
        this.file2TextConverter = file2TextConverter;
    }



    @Override
    protected void innerCancelHandle() {
        Thread processor = this.getAttr(EventAttrKey.EVENT_PROCESSOR);
        if (processor != null) {
            try {

                processor.stop();
            } catch (ThreadDeath e) {

            }
        }
    }
}
